<template>
  <div>
    <div class="header">
      <div class="page-header">
        <el-page-header @back="goBack" content="聊天室"></el-page-header>
      </div>
    </div>
    <div class="chat-room">
      <div class="top">
        <span class="top-text user">当前用户：{{ userInfo.userName }}</span>
        <span v-if="params.receiver" class="top-text chatting">正在和 {{ params.receiver }} 聊天中...</span>
      </div>
      <div class="message-box" ref="scrollContainer">
        <ul v-if="chatUser.username">
          <li :class="{ 'text-right': message.sender === userInfo.userName, 'text-left': message.sender !== userInfo.userName }"
              v-for="message in messages">
            <el-image v-if="message.sender !== userInfo.userName"
                      class="picture picture-friend"
                      :src="chatUser.avatar"></el-image>
            <div class="bubble-box bubble-box-friend" v-if="message.sender !== userInfo.userName">
              {{ message.content }}
            </div>
            <div class="bubble-box bubble-box-me" v-if="message.sender === userInfo.userName">
              {{ message.content }}
            </div>
            <el-image v-if="message.sender === userInfo.userName"
                      class="picture picture-me"
                      :src="userInfo.avatar"></el-image>
          </li>
        </ul>
      </div>

      <div class="friend-list">
        <el-aside width="200px">
          <el-menu :default-openeds="['1']">
            <el-submenu index="1">
              <template slot="title"><i class="el-icon-user-solid"></i>好友列表</template>
              <el-menu-item @click="chooseFriend(user)" v-for="user in userList"
                            :key="user.username"
                            :index="user.username">
                <el-image
                    :src="user.avatar"></el-image>
                <el-badge v-if="messageCount(user.username) !==0 " :value="messageCount(user.username)"
                          class="item">
                  {{ user.username }}
                </el-badge>

                <span v-if="messageCount(user.username) === 0"> {{ user.username }}</span>

              </el-menu-item>
            </el-submenu>
          </el-menu>
        </el-aside>
      </div>

      <div class="system-box">
        <el-divider></el-divider>
        <span slot="title"><i class="el-icon-message-solid"></i>  系统公告</span>
        <ul>
          <li v-for="user in userList">{{ user.username }} 已上线...</li>
        </ul>
      </div>

      <div class="input-box" ref="inputBox">
        <el-popover
            @show="handlePopoverShow"
            @hide="handlePopoverHide"
            ref="emojiBox"
            v-model="visible"
            :width="emojiBoxWidth"
            placement="top-start"
            trigger="click">
          <div class="emoji-grip">
            <div @click="selectEmoji(emoji)" class="emoji-item" v-for="(emoji, index) in emojis"
                 :key="index">
              <!--                    <i :class="icon.iconName"></i>-->
              <span>{{ emoji }}</span>
            </div>
          </div>
          <div slot="reference" class="emoji-icon">
            <img width="20px" :src="require('@/assets/images/emoji.png')" alt=""/>
          </div>
        </el-popover>
        <textarea ref="input" v-model="params.content" v-on:keydown.enter.prevent="sendMessage"
                  class="multi-line-input"></textarea>
        <el-button size="medium" @click="sendMessage" type="primary">发送</el-button>
      </div>

    </div>
  </div>
</template>

<script>
import {mapState} from "vuex";

export default {
  name: '',
  components: {},
  data() {
    return {
      // ws地址
      wsUrl: 'ws://127.0.0.1:8888/api/system/chat/',
      // ws实例
      websocket: null,
      totalMessages: [],
      userList: [],
      textarea: '',
      params: {
        type: 1,
        sender: '',
        receiver: '',
        content: '',
        readFlag: false,
      },
      chatUser: {},
      dialogVisible: false,
      emojiBoxWidth: 0,
      visible: false,
      emojis: ['😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '😉', '😊', '😇',
        '🥰', '😍', '🤩', '😘', '😗', '😚', '😙', '🥲', '😏', '😋', '😛', '😜',
        '🤪', '😝', '🤗', '🤭', '🫢', '🫣', '🤫', '🤔', '🫡', '🤤', '🤠', '🥳',
        '🥸', '😎', '🤓', '🧐', '🙃', '🫠', '🤐', '🤨', '😐', '😑', '😶', '🫥',
        '😶‍🌫', '😒', '🙄', '😬', '😮‍💨', '🤥', '🫨', '😌', '😔', '😪', '😴', '😷',
        '🤒', '🤕', '🤢', '🤮', '🤧', '🥵', '🥶', '🥴', '😵', '😵‍💫', '🤯', '🥱',
        '😕', '🫤', '😟', '🙁', '😮', '😯', '😲', '😳', '🥺', '🥹', '😦', '😧', '😨',
        '😰', '😥', '😢', '😭', '😱', '😖', '😣', '😞', '😓', '😩', '😫', '😤', '😡', '😠',
        '🤬', '👿', '😈', '👿', '💀', '💩', '🤡', '👹', '👺', '👻', '👽', '👾', '🤖', '😺',
        '😸', '😹', '😻', '😼', '😽', '🙀', '😿', '😾', '🙈', '🙉', '🙊'],
    };
  },
  //监听属性 类似于data概念
  computed: {
    ...mapState('user', ['userInfo']),
    messageCount() {
      return function (sender) {
        return this.totalMessages.filter(message => {
          return sender === message.sender && this.userInfo.userName !== sender
              && !message.readFlag
              && this.chatUser.username !== sender
        }).length;
      }
    },
    messages() {
      return this.totalMessages.filter(message => {
        if (this.arrayEquals([this.chatUser.username, this.userInfo.userName], [message.sender, message.receiver])) {
          return message.readFlag = true;
        }
      })
    },
  },
  mounted() {
    this.initWebSocket();

    this.$nextTick(() => {
      //设置表情包窗口大小
      this.setEmojiBoxWidth();
      // 初始化时滚动到底部
      this.scrollToBottom();
      //添加监听窗口改变时间
      window.addEventListener("resize", this.setEmojiBoxWidth);
    });

  },
  updated() {
    // 内容更新后滚动到底部
    this.scrollToBottom();
  },
  destroyed() {
    // 离开路由之后断开websocket连接
    this.websocket.close()
    //移除监听窗口改变事件
    window.removeEventListener("resize", this.setEmojiBoxWidth);
  },
  //方法集合
  methods: {
    // 初始化weosocket
    initWebSocket() {
      if (typeof WebSocket === 'undefined')
        return console.log('您的浏览器不支持websocket')
      this.websocket = new WebSocket(this.wsUrl + this.userInfo.userName, window.sessionStorage.getItem('token'))
      this.websocket.onopen = this.onOpen
      this.websocket.onmessage = this.OnMessage
      this.websocket.onerror = this.OnError
      this.websocket.onclose = this.onClose
    },
    onOpen() {
      window.console.log('WebSocket连接成功');
    },
    OnError() {
      // 连接建立失败重连
      this.initWebSocket()
    },
    OnMessage(e) {
      // 数据接收
      let message = JSON.parse(e.data)
      if (message.type === 0) {
        this.userList = message.content;
      } else {
        console.log('接收的数据', message)
        this.totalMessages.push(message)
      }

    },
    onClose(e) {
      // 关闭
      console.log('断开连接', e)
    },
    sendMessage() {
      if (this.params.content) {
        this.params.sender = this.userInfo.userName

        let json = JSON.stringify(this.params);

        if (this.params.sender && this.params.receiver) {

          if (this.params.sender !== this.params.receiver) {
            // 数据发送
            this.websocket.send(json)
          }

          let message = JSON.parse(json);

          this.totalMessages.push(message)
        }

        //消息发送后关闭表情包窗口
        if (this.visible) {
          this.$refs.emojiBox.doClose()
        }

        this.params.content = ''

        this.$refs.input.focus();
      }
    },
    chooseFriend(user) {
      let users = [user.username, this.userInfo.userName]
      this.totalMessages.filter(message => {
        if (message.sender === user.username && message.readFlag === false) {
          message.readFlag = true
        }
        return this.arrayEquals([message.sender, message.receiver], users)
      })
      this.params.receiver = user.username;
      this.chatUser = user;
    },
    selectEmoji(emoji) {
      this.params.content = this.params.content + emoji
      this.$refs.input.focus();
    },
    scrollToBottom() {
      const container = this.$refs.scrollContainer;
      container.scrollTop = container.scrollHeight;
    },
    setEmojiBoxWidth() {
      this.$refs.emojiBox.doClose();
      this.emojiBoxWidth = this.$refs.inputBox.offsetWidth * 0.8;
    },
    handlePopoverShow() {
      this.visible = true
    },
    handlePopoverHide() {
      this.visible = false
    },
    goBack() {
      window.history.back()
    },
    arrayEquals(a, b) {
      // 如果数组长度不同，则它们不相等
      if (a.length !== b.length) {
        return false;
      }
      // 对数组进行排序
      const sortedA = a.sort();
      const sortedB = b.sort();
      // 逐个比较排序后的元素
      for (let i = 0; i < sortedA.length; i++) {
        if (sortedA[i] !== sortedB[i]) {
          return false;
        }
      }
      return true;
    }

  }
};
</script>

<style scoped>

.header {
  /*display: flex;*/
  /*!*垂直对齐*!*/
  /*align-items: center;*/
  height: 50px;
  background-color: #eff4f9;
}

.page-header {
  float: left;
  margin-top: 15px
}

.chat-room {
  width: 100%;
  height: calc(100vh - 130px);
  border-radius: 4px;
  border: 1px solid #ebeef5;
  background-color: #fff;
  overflow: hidden;
  color: #303133;
  transition: .3s;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
  position: relative;
}

.top {
  height: 50px;
  background: #3e95f5;
  position: relative;
}

.top .top-text {
  line-height: 50px;
}

.top .user {
  position: absolute;
  left: 20px;
  color: white;
}

.top .chatting {
  position: absolute;
  left: calc(100% / 2 - 120px);
  bottom: 0;
  color: white;
  font-size: 13px;
}

.message-box {
  width: calc(100% - 200px);
  height: 70%;
  border: 1px solid #CDCDCD;
  overflow-y: scroll;
  position: relative;
}

.message-box .picture {
  width: 30px;
  height: 30px;
  margin-top: 5px
}

.message-box .picture-friend {
  margin-left: 10px;
}


.message-box .picture-me {
  margin-right: 10px;
}

.bubble-box {
  display: inline-block;
  line-height: 1;
  cursor: pointer;
  background: #FFF;
  border: 1px solid #DCDFE6;
  color: #606266;
  -webkit-appearance: none;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: .1s;
  transition: .1s;
  font-weight: 500;
  padding: 10px 10px;
  font-size: 14px;
  border-radius: 4px;
  max-width: calc(100% / 2 - 100px);
  word-wrap: break-word;
  text-align: left;
  vertical-align: top;
}

.bubble-box-friend {
  margin-left: 5px;
}

.bubble-box-me {
  margin-right: 5px;
}

.message-box ul li {
  line-height: 40px;
  padding: 8px 0;
}


.text-left {
  text-align: left;
}

.text-right {
  text-align: right;
}

.friend-list {
  width: 200px;
  height: 50%;
  vertical-align: top;
  position: absolute;
  right: 0;
  top: 50px;
  border-right: 1px solid #CDCDCD;
  border-top: 1px solid #CDCDCD;
}

.friend-list .el-image {
  width: 25px;
  height: 25px
}

.friend-list .el-aside {
  background-color: rgb(238, 241, 246);
  overflow: hidden;
}

.system-box {
  width: 200px;
  height: 50%;
  position: absolute;
  right: 0;
  top: calc(50% + 50px);
  border-right: 1px solid #CDCDCD;
  border-bottom: 1px solid #CDCDCD;
}

.system-box span {
  position: absolute;
  margin-left: 20px;
  top: 40px;
}

.system-box ul {
  padding: 10px 0;
}

.system-box ul li {
  line-height: 20px;
  height: 20px;
  margin-left: 30px;
  font-size: 13px;
  padding: 13px 0;
  color: #797777;
}

.input-box {
  height: 30%;
  width: calc(100% - 200px);
  border-left: 1px solid #CDCDCD;
  border-right: 1px solid #CDCDCD;;
  position: relative;

}

.input-box .el-button {
  position: absolute;
  right: 20px;
  bottom: 60px;
}

.el-submenu .el-menu-item {
  height: 35px;
  line-height: 35px;
}

.multi-line-input {
  position: absolute;
  top: 25px;
  bottom: 0;
  left: 0;
  right: 0;
  width: 80%;
  height: 100%;
  padding: 5px;
  font-size: 14px;
  line-height: 1.5;
  border: 1px solid white;
  outline: none;
  resize: none;
}

.emoji-icon {
  position: absolute;
  top: 5px;
  left: 5px;
}

.emoji-grip {
  height: calc((100vh - 130px - 50px) * 0.5);
  overflow-y: scroll;
  overflow-x: hidden;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  justify-content: center;
  align-items: center;
}

.emoji-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-size: 25px;
  width: 5%;
  height: 35px;
  cursor: pointer
}
</style>
